using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Platform.algorithm;
using Platform.ChooseTextPanel;

namespace Platform
{
    public partial class Platform : Form
    {
        private DrawCanvas mycanvas;
        private TextPanel txtpan;
        public Platform()
        {
            InitializeComponent();
        }
        public void InitialApp()
        {
            mycanvas = new DrawCanvas();
            mycanvas.SetWidth(document.Width);
            txtpan = new TextPanel();
            ShowStatusText();
            KnowledgeBase.Create();
            textBox1.Visible = true;
            textBox1.Focus();
        }

        private void Platform_Load(object sender, EventArgs e)
        {
            this.InitialApp();
        }

        private void document_MouseClick(object sender, MouseEventArgs e)
        {
            mycanvas.UpdateCursor(e.Location);            
            inputtxt.Visible = false;
            txtpan.Dispose();
            document.Refresh();
        }

        private void document_Paint(object sender, PaintEventArgs e)
        {
            int cheight = mycanvas.GetHeight();
            int aheight = scrollarea.Height;
            int x = this.scrollarea.VerticalScroll.Value - 50;
            int y = x + this.scrollarea.Height + 50;
            Graphics g = e.Graphics;
            mycanvas.SetWidth(document.Width);
            mycanvas.Draw(g,x,y);
            document.Height = (cheight > aheight ? cheight + 20 : aheight - 1);
        }
        private void SelectKeyPress(string key)
        {
            if (txtpan.Code != "")
            {
                txtpan.GetCode();
            }
            else
            {
                mycanvas.AddElement(new Element(key));
                txtpan.Dispose();
            }
        }
        private void PunctuationPress(char keychar)
        {            
            if (txtpan.Code == "")
            {
                string code = "DOUHAO";
                switch (keychar)
                {
                    case ',': code = "DOUHAO"; break;
                    case '.': code = "JUHAO"; break;
                    case '?': code = "WENHAO"; break;
                    case '!': code = "TANHAO"; break;
                    case '\\': code = "DUNHAO"; break;
                    case ':': code = "MAOHAO"; break;
                    default: return;
                }
                mycanvas.AddElement(new Element(code));
                txtpan.Dispose();
            }
        }
        private void AutoComplete()
        {
            if (txtpan.Code.Length == 0) return;
            if (txtpan.InputComplete())
            {
                Element e = txtpan.GetCode();
                if (e != null)
                {
                    mycanvas.AddElement(e);
                    txtpan.Dispose();
                }
            }
        }
        private void EngInput(char key)
        {
            if (!document.Visible) return;
            switch (key)
            {
                case '=': txtpan.NextPage(); break;
                case '-': txtpan.PreviousPage(); break;
                case (char)Keys.Space: SelectKeyPress("SPACE"); break;
                case (char)Keys.Enter: SelectKeyPress("ENTER"); break;
                case (char)Keys.Tab: SelectKeyPress("TABLE"); break;
                case (char)Keys.Escape: txtpan.Dispose(); break;
                case '\b': if (txtpan.Code == "") mycanvas.DeletePrevious(); else txtpan.AddCode(key.ToString()); break;
                case (char)Keys.Delete: if (txtpan.Code == "") mycanvas.DeleteNext(); break;
                default: txtpan.AddCode(key.ToString()); break;
            }
            PunctuationPress(key);
            AutoComplete();
            if (txtpan.Code != "")
            {
                inputtxt.Visible = true;
            }
            else
            {
                document.Refresh();
                inputtxt.Visible = false;
            }
            inputtxt.Refresh();
            AdjustInputLocation();
            scrollToCursor();
        }
        private void Platform_KeyPress(object sender, KeyPressEventArgs e)
        {
            //EngInput(e.KeyChar);
        }
        private void inputtxt_Paint(object sender, PaintEventArgs e)
        {            
            txtpan.Draw(e.Graphics);
            inputtxt.Width = txtpan.Width;
        }

        private void savefile_Click(object sender, EventArgs e)
        {
            if (mycanvas.GetCurrentFile() != "")
            {
                mycanvas.SaveFile();
                return;
            }
            else
            {
                DialogResult re = saveCurrentFile.ShowDialog();
                if (re == DialogResult.OK)
                {
                    mycanvas.SaveFile(saveCurrentFile.FileName);
                }
            }
        }

        private void openfile_Click(object sender, EventArgs e)
        {            
            if(!WindowsClose()) return;
            DialogResult re = openNewFile.ShowDialog();
            if (re == DialogResult.OK)
            {
                mycanvas = new DrawCanvas();
                mycanvas.OpenFile(openNewFile.FileName);
            }            
            Refresh();
        }
        private bool WindowsClose()
        {
            if (!mycanvas.ShouldSave()) return true;
            DialogResult re = MessageBox.Show("Your document has been changed.\n\nDo you want to save it?", "Confirm your operation", MessageBoxButtons.YesNoCancel);
            if (re == DialogResult.Cancel) return false;
            else if (re == DialogResult.No) return true;
            else if (re == DialogResult.Yes)
            {
                string file = mycanvas.GetCurrentFile();
                if (file.Length == 0)
                {
                    DialogResult result = saveCurrentFile.ShowDialog();
                    if (result == DialogResult.OK)
                    {
                        file = saveCurrentFile.FileName;
                    }
                    else return false;
                }
                mycanvas.SaveFile(file);
                return true; 
            }
            else return false;
        }

        private void Platform_FormClosing(object sender, FormClosingEventArgs e)
        {
            bool b = WindowsClose();
            e.Cancel = !b;
        }

        private void newfile_Click(object sender, EventArgs e)
        {
            if (!WindowsClose()) return;
            mycanvas = new DrawCanvas();
            document.Refresh();
        }

        private void saveas_Click(object sender, EventArgs e)
        {            
            DialogResult re = saveCurrentFile.ShowDialog();
            if (re == DialogResult.OK)
            {
                mycanvas.SaveFile(saveCurrentFile.FileName);
            }            
        }
        private void AdjustInputLocation()
        {
            Point p = mycanvas.GetCursorPoint();
            int y = p.Y;
            if (y > 50) y -= 40;
            int x = p.X + 50;
            if (x + inputtxt.Width > document.Width)
                x = p.X - 50 - inputtxt.Width;
            inputtxt.Top = y;
            inputtxt.Left = x;
            textBox1.Top = y;
            textBox1.Left = x;
        }

        private void viewCode_Click(object sender, EventArgs e)
        {
            if (codeViewer.Visible)
            {
                codeViewer.Visible = false;
                document.Visible = true;
                viewCode.Text = "View Code";
            }
            else
            {
                codeViewer.Visible = true;
                codeViewer.Text = mycanvas.GetCode();
                document.Visible = false;
                viewCode.Text = "View Text";
            }
        }
        private void ShowStatusText()
        {
            string txt = Util.GetFileTxt(Application.StartupPath + @"\txt\struct.txt", Encoding.GetEncoding(936));
            hinttxt2.Text = txt.Substring(0, 45);
            hinttxt.Text = txt.Substring(45);
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            Setting s = new Setting();
            s.ShowDialog();
        }

        private void Platform_MouseWheel(object sender, MouseEventArgs e)
        {            
            if (!scrollarea.VerticalScroll.Visible) return;
            if (e.X > 0 && e.X < this.scrollarea.Width && e.Y > 30 && e.Y < this.scrollarea.Height)
            {
                int max = this.scrollarea.VerticalScroll.Maximum;
                int min = this.scrollarea.VerticalScroll.Minimum;
                int newVal = this.scrollarea.VerticalScroll.Value - e.Delta / 3;
                newVal = newVal < min ? min : newVal;
                newVal = newVal > max ? max : newVal;
                if (newVal >= min && newVal <= max)
                    this.scrollarea.VerticalScroll.Value = newVal;
            }
        }
        private bool PointInView(int x, int y)
        {
            return x > document.Left && x < document.Width && y > this.scrollarea.VerticalScroll.Value + 2 && y < this.scrollarea.VerticalScroll.Value + this.scrollarea.Height - 70;
        }
        private void scrollToCursor()
        {
            Point p = mycanvas.GetCursorPoint();
            if(PointInView(p.X,p.Y)) return;
            int newval = p.Y - this.scrollarea.Height + 70;
            newval = newval < this.scrollarea.VerticalScroll.Minimum ? this.scrollarea.VerticalScroll.Minimum : newval;
            newval = newval > this.scrollarea.VerticalScroll.Maximum ? this.scrollarea.VerticalScroll.Maximum : newval;
            this.scrollarea.VerticalScroll.Value = newval;
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            string txt = textBox1.Text.Trim();
            if (txt.Length > 0)
            {
                for (int i = 0; i < txt.Length; ++i)
                {
                    string temp = txt.Substring(i, 1);
                    byte[] data = Encoding.Unicode.GetBytes(temp);
                    if (data.Length > 1 && data[1] == 0)
                    {
                        char[] arr = temp.ToCharArray();
                        foreach (char c in arr)
                        {
                            EngInput(c);
                        }
                    }
                    else
                    {
                        string high = String.Format("{0:X}", data[0]);
                        if (high.Length == 1) high = "0" + high;
                        string low = String.Format("{0:X}", data[1]);
                        if (low.Length == 1) low = "0" + low;
                        mycanvas.AddItemFromUnicode(low + high); 
                    }
                }
                textBox1.Text = "";
                this.document.Invalidate();
                this.document.Update();
                AdjustInputLocation();
            }
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter || e.KeyChar == (char)Keys.Back || e.KeyChar == (char)Keys.Space)
                EngInput(e.KeyChar);
        }
    }
}